﻿using System.ServiceProcess;
using FLib;
using LibraryGuard.Interfaces;
using LibraryGuard.Utilities;
using System;

namespace LibraryGuard
{
	/// <summary>
	/// LibraryGuard service.
	/// </summary>
	public sealed class LibraryGuardService
		: ServiceBase
	{
		#region Logger
		private static NLog.Logger Logger = NLog.LogManager.GetLogger("Service");
		#endregion

		#region Config
		public const string Name = "LibraryGuardService";
		#endregion

		#region Private fields
		private readonly ConfigLoader ConfigLoader = null;
		private readonly IActionList ActionList = null;
		private ContinuousMode Continuous = null;
		private Scheduler Scheduler = null;
		private IMode Mode = null;
		#endregion

		#region Constructor
		public LibraryGuardService(ConfigLoader cfg)
		{
			Validate.Debug(() => cfg, v => v.NotNull());

			this.ConfigLoader = cfg;
			this.ActionList = new ActionList();

			this.ServiceName = Name;
			this.AutoLog = false;
			this.CanStop = true;
			this.CanPauseAndContinue = true;
		}
		#endregion

		#region Overrides
		protected override void OnStart(string[] args)
		{
			Logger.Info("Starting service");
			if (!this.ConfigLoader.Run(this.ActionList))
			{
				this.ExitCode = -2;
				this.Stop();
				return;
			}

			if (this.ConfigLoader.Configuration.Continuous)
			{
				this.Continuous = new ContinuousMode(this.ConfigLoader.Configuration, this.ConfigLoader.Guards);
				this.Continuous.Run();
			}

			this.Mode = Modes.Factory.CreateServiceMode(this.ConfigLoader.Configuration, this.ConfigLoader.Guards, this.ActionList);

			if (this.ConfigLoader.Configuration.DueTime != TimeSpan.Zero)
			{
				this.Scheduler = new Scheduler(this.Mode, this.ConfigLoader.Configuration.DueTime, this.ConfigLoader.Configuration.WorkingTime);
				this.Scheduler.Start();
			}
			else
				this.Mode.Start();

			Logger.Info("Service started");
		}

		protected override void OnStop()
		{
			if (this.Continuous != null)
			{
				this.Continuous.Dispose();
				this.Continuous = null;
			}
			if (this.Scheduler != null)
				this.Scheduler.Stop();

			if (this.Mode.State != ModeState.Stopped)
				this.Mode.Stop(true);

			this.ActionList.Clear();
			this.Mode.Dispose();
			this.Mode = null;

			this.Scheduler = null;

			Logger.Info("Service stopped");
		}

		protected override void OnPause()
		{
			this.Continuous.Disable();
			if (this.Scheduler != null)
				this.Scheduler.Stop();
			if (this.Mode.State == ModeState.Running)
				this.Mode.Pause();
			Logger.Info("Service paused");
		}

		protected override void OnContinue()
		{
			this.Continuous.Enable();
			if (this.Scheduler != null)
				this.Scheduler.Start();
			else
				this.Mode.Resume();
			Logger.Info("Service resumed");
		}
		#endregion
	}
}
